import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import squarify  # 树状图库
import matplotlib.dates as mdates
from matplotlib.font_manager import FontProperties
from dateutil.relativedelta import relativedelta

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # Windows
plt.rcParams['axes.unicode_minus'] = False

# 读取数据
baby = pd.read_csv(r'C:\third\深度学习\作业\课设\tianchi_mum_baby.csv')
trade = pd.read_csv(r'C:\third\深度学习\作业\课设\tianchi_mum_baby_trade_history.csv')

# 合并数据
data = pd.merge(baby, trade, on='user_id')

# 数据预处理
def preprocess_data(df):
    if 'buy_mount' in df.columns:
        df = df.rename(columns={'buy_mount': 'buy_amount'})
        print("已将列名'buy_mount'重命名为'buy_amount'")

    # 日期格式转换
    df['day'] = pd.to_datetime(df['day'], format='%Y%m%d')
    df['birthday'] = pd.to_datetime(df['birthday'], format='%Y%m%d')
    
    # 计算婴儿年龄（天）
    df['age_days'] = (df['day'] - df['birthday']).dt.days.abs()
    
    # 年龄分段
    bins = [0, 180, 365, 730, 1095, 1460, 1825, 2190]
    labels = ['0-6月', '6-12月', '1-2岁', '2-3岁', '3-4岁', '4-5岁', '5-6岁']
    df['age_group'] = pd.cut(df['age_days'], bins=bins, labels=labels)
    
    # 性别映射
    gender_map = {0: '男孩', 1: '女孩', 2: '未知'}
    df['gender'] = df['gender'].map(gender_map)
    
    # 日期特征提取
    df['year'] = df['day'].dt.year
    df['quarter'] = df['day'].dt.quarter
    df['month'] = df['day'].dt.month
    df['weekday'] = df['day'].dt.weekday
    df['is_weekend'] = df['weekday'].isin([5, 6])
    
    return df

data = preprocess_data(data)

# 1. 流量分析：时间维度销量规律
def plot_time_analysis(df):
    plt.figure(figsize=(18, 12))
    
    # 1.1 年度/季度销量趋势
    plt.subplot(2, 2, 1)
    # 正确重组数据结构
    quarter_sales = (df.groupby(['year', 'quarter'])['buy_amount'].sum()
                .unstack(level=0))  # 年份作为列

    # 创建季度-年份的横轴标签
    x_labels = [f"{year}Q{quarter}" 
           for year in quarter_sales.columns 
           for quarter in quarter_sales.index]

    # 准备绘图数据
    plot_data = quarter_sales.T.stack().reset_index(name='sales')
    plot_data['period'] = plot_data['year'].astype(str) + 'Q' + plot_data['quarter'].astype(str)

    # 绘制趋势线
    sns.lineplot(data=plot_data, 
            x='period', 
            y='sales', 
            hue='year',
            marker='o',
            palette='viridis')

    plt.title('年度/季度销量趋势 (2012-2015)')
    plt.xlabel('季度')
    plt.ylabel('销量')
    plt.legend(title='年份')
    plt.xticks(rotation=45)  # 旋转标签防止重叠
    
    # 1.2 月度销量热力图
    plt.subplot(2, 2, 2)
    month_sales = df.groupby(['year', 'month'])['buy_amount'].sum().unstack().T
    sns.heatmap(month_sales, annot=True, fmt=".0f", cmap="YlGnBu")
    plt.title('月度销量热力图')
    plt.xlabel('年份')
    plt.ylabel('月份')
    
    # 1.3 日销量分布（工作日vs周末）
    plt.subplot(2, 2, 3)
    weekday_names = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
    weekday_sales = df.groupby('weekday')['buy_amount'].sum()
    weekday_sales.index = weekday_names
    sns.barplot(x=weekday_sales.index, y=weekday_sales.values, palette="Blues_d")
    plt.title('周内销量分布')
    plt.xlabel('星期')
    plt.ylabel('销量')
    
    # 1.4 不同年龄段的购买时间偏好
    plt.subplot(2, 2, 4)
    age_time = df.groupby(['age_group', 'quarter'])['buy_amount'].sum().unstack()
    sns.heatmap(age_time, annot=True, fmt=".0f", cmap="YlOrRd")
    plt.title('不同年龄段季度购买偏好')
    plt.xlabel('季度')
    plt.ylabel('年龄段')
    
    # 手动调整子图布局
    plt.subplots_adjust(top=0.96, bottom=0.13, left=0.10, right=0.95, hspace=0.30,
                        wspace=0.35)
    plt.savefig('时间维度分析.png', dpi=300)
    plt.show()

# 2. 类别分析：高价值类目识别
def plot_category_analysis(df):
    plt.figure(figsize=(18, 12))
    
    # 2.1 一级类目销量占比
    plt.subplot(2, 2, 1)
    cat1_sales = df.groupby('category_1')['buy_amount'].sum().nlargest(10)
    plt.pie(cat1_sales, labels=cat1_sales.index, autopct='%1.1f%%')
    plt.title('一级类目销量占比Top10')
    
    # 2.2 二级类目树状图
    plt.subplot(2, 2, 2)
    # 选择销量最高的一级类目下的二级类目
    top_cat1 = cat1_sales.index[0]
    cat2_data = df[df['category_1'] == top_cat1]
    cat2_sales = cat2_data.groupby('category_2')['buy_amount'].sum().nlargest(20)
    
    # 树状图
    squarify.plot(sizes=cat2_sales.values, 
                 label=[f'{idx}\n{val:.0f}' for idx, val in zip(cat2_sales.index, cat2_sales.values)],
                 alpha=0.8, color=plt.cm.Paired.colors)
    plt.title(f'一级类目 {top_cat1} 下的二级类目销量分布')
    plt.axis('off')
    
    # 2.3 类目季度热力图
    plt.subplot(2, 2, 3)
    cat_quarter = df.groupby(['category_1', 'quarter'])['buy_amount'].sum().unstack().nlargest(10, columns=[1,2,3,4]).sum(axis=1)
    cat_quarter = df.groupby(['category_1', 'quarter'])['buy_amount'].sum().unstack()
    top_cats = cat_quarter.sum(axis=1).nlargest(8).index
    sns.heatmap(cat_quarter.loc[top_cats], annot=True, fmt=".0f", cmap="YlGnBu")
    plt.title('Top类目季度销量分布')
    plt.xlabel('季度')
    plt.ylabel('一级类目')
    
    # 2.4 高价值类目分析（销量与用户数）
    plt.subplot(2, 2, 4)
    cat_value = df.groupby('category_1').agg(
        total_sales=('buy_amount', 'sum'),
        user_count=('user_id', pd.Series.nunique)
    ).nlargest(10, 'total_sales')
    
    sns.scatterplot(data=cat_value, x='user_count', y='total_sales', size='total_sales', hue=cat_value.index,
                   sizes=(100, 1000), alpha=0.8, legend=False)
    
    # 添加标注
    for i, row in cat_value.iterrows():
        plt.annotate(i, (row['user_count'], row['total_sales']), 
                    xytext=(5, 5), textcoords='offset points')
    
    plt.title('类目价值分析：销量 vs 用户数')
    plt.xlabel('购买用户数')
    plt.ylabel('总销量')
    
    # 手动调整子图布局
    plt.subplots_adjust(top=0.95, bottom=0.13, left=0.10, right=0.95, hspace=0.30,
                        wspace=0.35)
    plt.savefig('类目分析.png', dpi=300)
    plt.show()

# 3. 性别分析：购买行为差异
def plot_gender_analysis(df):
    # 创建2x2的子图网格（包含雷达图位置）
    fig = plt.figure(figsize=(18, 12))
    ax1 = plt.subplot(2, 2, 1)  # 3.1 性别销量对比
    ax2 = plt.subplot(2, 2, 2, projection='polar')  # 3.2 性别类目偏好雷达图
    ax3 = plt.subplot(2, 2, 3)  # 3.3 年龄-性别交叉分析
    ax4 = plt.subplot(2, 2, 4)  # 3.4 性别与类目交叉分析

    # 3.1 性别销量对比
    gender_sales = df.groupby('gender')['buy_amount'].sum()
    sns.barplot(x=gender_sales.index, y=gender_sales.values, palette="pastel", ax=ax1)
    ax1.set_title('性别销量对比', y=1.05)
    ax1.set_xlabel('性别')
    ax1.set_ylabel('总销量')

    # 3.2 性别类目偏好雷达图
    # 选择Top5类目
    top_categories = df.groupby('category_1')['buy_amount'].sum().nlargest(5).index
    
    # 计算每个性别在每个类目的购买比例
    radar_data = []
    for gender in ['男孩', '女孩', '未知']:
        gender_data = df[df['gender'] == gender]
        cat_sales = gender_data.groupby('category_1')['buy_amount'].sum()
        cat_sales = cat_sales.reindex(top_categories, fill_value=0)
        total_sales = cat_sales.sum()
        radar_data.append((cat_sales / total_sales).values)
    
    # 雷达图参数
    angles = np.linspace(0, 2*np.pi, len(top_categories), endpoint=False).tolist()
    angles += angles[:1]  # 闭合
    
    # 绘制雷达图
    for i, (values, gender) in enumerate(zip(radar_data, ['男孩', '女孩', '未知'])):
        values = np.append(values, values[0])
        ax2.plot(angles, values, 'o-', linewidth=2, label=gender)
        ax2.fill(angles, values, alpha=0.1)
    
    # 设置标签
    ax2.set_xticks(angles[:-1])
    ax2.set_xticklabels(top_categories)
    ax2.set_title('性别类目偏好雷达图')
    ax2.legend(loc='upper right')

    # 3.3 年龄-性别交叉分析
    age_gender = df.groupby(['age_group', 'gender'])['buy_amount'].sum().unstack()
    age_gender = age_gender.div(age_gender.sum(axis=1), axis=0)  # 标准化
    sns.heatmap(age_gender, annot=True, fmt=".2f", cmap="YlGnBu", annot_kws={"size": 8}, ax=ax3)
    ax3.set_title('不同年龄段性别购买比例')
    ax3.set_xlabel('性别')
    ax3.set_ylabel('年龄段')

    # 3.4 性别与类目交叉分析
    gender_cat = df.groupby(['gender', 'category_1'])['buy_amount'].sum().unstack().fillna(0)
    top_gender_cat = gender_cat.sum().nlargest(8).index
    gender_cat = gender_cat[top_gender_cat]
    
    gender_cat.plot(kind='bar', stacked=True, colormap='viridis', ax=ax4)
    ax4.set_title('性别-类目销量分布')
    ax4.set_xlabel('性别')
    ax4.set_ylabel('销量')
    ax4.legend(title='类目', bbox_to_anchor=(1.05, 1), loc='upper left')
    ax4.set_xticklabels(ax4.get_xticklabels(), rotation=0)

    # 调整布局并保存
    plt.subplots_adjust(top=0.95, bottom=0.13, left=0.10, right=0.90, hspace=0.30, wspace=0.05)
    plt.savefig('性别分析.png', dpi=300, bbox_inches='tight')
    plt.show()

# 4. 扩展分析：多维交叉洞察
def plot_advanced_analysis(df):
    plt.figure(figsize=(18, 12))
    
    # 4.1 年龄阶段类目转移桑基图（简化版）
    # 注意：完整桑基图需要sankey库，这里用折线图展示趋势
    plt.subplot(2, 2, 1)
    age_cat = df.groupby(['age_group', 'category_1'])['buy_amount'].sum().unstack().fillna(0)
    top_cats = age_cat.sum().nlargest(3).index
    
    for cat in top_cats:
        sns.lineplot(x=age_cat.index, y=age_cat[cat], label=cat, marker='o')
    
    plt.title('核心类目随年龄变化趋势')
    plt.xlabel('年龄段')
    plt.ylabel('销量')
    plt.legend(title='类目')
    
    # 4.2 复购率分析
    plt.subplot(2, 2, 2)
    # 计算用户购买次数
    user_orders = df.groupby('user_id')['day'].nunique().reset_index()
    user_orders.columns = ['user_id', 'order_count']
    
    # 复购用户定义：购买2次及以上
    repurchase_rate = (user_orders[user_orders['order_count'] >= 2].shape[0] / 
                      user_orders.shape[0]) * 100
    
    # 复购间隔分布
    repurchase_users = user_orders[user_orders['order_count'] >= 2]['user_id']
    repurchase_data = df[df['user_id'].isin(repurchase_users)]
    first_purchase = repurchase_data.groupby('user_id')['day'].min().reset_index()
    last_purchase = repurchase_data.groupby('user_id')['day'].max().reset_index()
    purchase_interval = pd.merge(first_purchase, last_purchase, on='user_id')
    purchase_interval['days_diff'] = (purchase_interval['day_y'] - purchase_interval['day_x']).dt.days
    
    # 绘制复购分析
    plt.bar(['复购率'], [repurchase_rate], color='skyblue')
    plt.text(0, repurchase_rate+1, f'{repurchase_rate:.1f}%', ha='center')
    plt.title(f'用户复购率: {repurchase_rate:.1f}%')
    plt.ylabel('百分比')
    
    # 4.3 复购间隔分布
    plt.subplot(2, 2, 3)
    sns.histplot(purchase_interval['days_diff'], bins=30, kde=True)
    plt.title('复购用户购买间隔分布')
    plt.xlabel('首次到最后次购买间隔(天)')
    plt.ylabel('用户数')
    
    # 4.4 异常购买识别
    plt.subplot(2, 2, 4)
    sns.boxplot(x=df['buy_amount'])
    plt.title('单次购买数量分布')
    plt.xlabel('购买数量')
    
    # 标记异常值
    q1 = df['buy_amount'].quantile(0.25)
    q3 = df['buy_amount'].quantile(0.75)
    iqr = q3 - q1
    upper_bound = q3 + 1.5 * iqr
    plt.axvline(x=upper_bound, color='r', linestyle='--')
    plt.text(upper_bound+1, 0.5, f'异常阈值: {upper_bound:.1f}', rotation=90)
    
    # 手动调整子图布局
    plt.subplots_adjust(top=0.95, bottom=0.13, left=0.10, right=0.95, hspace=0.30,
                        wspace=0.35)
    plt.savefig('扩展分析.png', dpi=300)
    plt.show()

# 执行所有分析
plot_time_analysis(data)
plot_category_analysis(data)
plot_gender_analysis(data)
plot_advanced_analysis(data)

# 保存预处理数据
data.to_csv('processed_mum_baby_data.csv', index=False)